package cn.mhome.merchant.dao.spring.data.repository.entity;

import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.mhome.merchant.entity.common.enums.DateString;
import cn.mhome.merchant.entity.common.enums.MapType;
import cn.mhome.merchant.entity.common.enums.Mapping;
import cn.mhome.merchant.util.DateUtil;

/**
 * bean对象的映射
 */
public class EntityMapper {
    private static final Logger LOGGER = LoggerFactory.getLogger(EntityMapper.class);

    /**
     * 映射成对象
     * 
     * @param rs
     * @param clazz
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object mapperObject(Map<Object, Object> map, @SuppressWarnings("rawtypes") Class clazz) {
        Object instance = null;
        try {
            // 判断如果结果集不存在的话 就返回null
            if (map == null || map.size() == 0) {
                return instance;
            }
            Map<String, Field> fieldMap = new HashMap<String, Field>();
            Map<String, FieldMapper> fieldMapperMap = new HashMap<String, FieldMapper>();
            Field[] fields = clazz.getDeclaredFields();
			boolean mapping = clazz.isAnnotationPresent(Mapping.class);
            if (mapping) {
            	Mapping mapenum = (Mapping)clazz.getAnnotation(Mapping.class);
                for (Field field : fields) {
                    // 4、获取注解上的role值
                	if(mapenum.type() == MapType.underline){
                		fieldMap.put(field.getName(), field);
                	}else{
                		String lineName = convertHump2Line(field.getName());
                		fieldMap.put(lineName, field);
                	}
                }
            } else {
                for (Field field : fields) {
                    boolean b = field.isAnnotationPresent(FieldMapper.class);
                    if (b) {
                        // 4、获取注解上的role值
                        FieldMapper fieldMapper = field.getAnnotation(FieldMapper.class);
                        fieldMap.put(fieldMapper.name(), field);
                        fieldMapperMap.put(fieldMapper.name(), fieldMapper);
                    }
                }
            }
            instance = clazz.newInstance();
            for (Map.Entry<Object, Object> entry : map.entrySet()) {
                Object key = entry.getKey();
                Object value = entry.getValue();
                initInstance(fieldMap, fieldMapperMap, mapping, instance,key,value);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("", e);
        }
        return instance;
    }

    /**
     * 
     * @param fieldName
     * @return
     */
    private static String convertHump2Line(String fieldName) {
    	StringBuilder sb = new StringBuilder();
    	for(char ca : fieldName.toCharArray()){
    		int num = (int)ca;
    		if(num >= 97 && num < 122){
    			sb = sb.append(ca);
    		}else{
    			sb = sb.append("_"+String.valueOf(ca).toLowerCase());
    		}
    	}
		return sb.toString();
	}
    
    public static void main(String[] args) {
		System.out.println(convertHump2Line("projectId"));
	}

	/**
     * 映射成List集合
     * 
     * @param rs
     * @param clazz
     * @return
     */
    public static Object mapperList(List<Map<Object, Object>> list, Class<?> clazz) {
        List<Object> targetList = new ArrayList<Object>();
        try {
            // 判断如果结果集不存在的话 就返回null
            if (list == null || list.size() == 0) {
                return targetList;
            }

            Map<String, Field> fieldMap = new HashMap<String, Field>();
            Map<String, FieldMapper> fieldMapperMap = new HashMap<String, FieldMapper>();
            Field[] fields = clazz.getDeclaredFields();
            boolean mapping = clazz.isAnnotationPresent(Mapping.class);
            Mapping mappEnum = clazz.getAnnotation(Mapping.class);
            if (mapping) {
                for (Field field : fields) {
                    // 4、获取注解上的role值
                    if(mappEnum.type() == MapType.hump){
                    	fieldMap.put(getFieldName(field), field);
                    }else{
                    	fieldMap.put(field.getName(), field);
                    }
                }
            } else {
                for (Field field : fields) {
                    boolean b = field.isAnnotationPresent(FieldMapper.class);
                    if (b) {
                        // 4、获取注解上的role值
                        FieldMapper fieldMapper = field.getAnnotation(FieldMapper.class);
                        fieldMap.put(fieldMapper.name(), field);
                        fieldMapperMap.put(fieldMapper.name(), fieldMapper);
                    }
                }
            }

            for (int i = 0; i < list.size(); i++) {
                Object instance = clazz.newInstance();
                Map<Object, Object> map = list.get(i);
                for (Map.Entry<Object, Object> entry : map.entrySet()) {
                    Object key = entry.getKey();
                    Object value = entry.getValue();
                    initInstance(fieldMap, fieldMapperMap, mapping, instance, key, value);
                }
                targetList.add(instance);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("", e);
        }
        return targetList;
    }

	private static String getFieldName(Field field) {
		String fieldName = field.getName();
		char[] chars = fieldName.toCharArray();
		StringBuilder sb = new StringBuilder();
		for(char c : chars){
			if(Character.isUpperCase(c)){
				sb = sb.append("_").append(String.valueOf(c).toLowerCase());
			}else{
				sb = sb.append(c);
			}
		}
		return sb.toString();
	}

	private static void initInstance(Map<String, Field> fieldMap, Map<String, FieldMapper> fieldMapperMap,
			boolean mapping, Object instance, Object key, Object value) throws IllegalAccessException {
		if (fieldMap.containsKey(key)) {
		    FieldType type = null;
		    boolean format = false;

		    Field field = fieldMap.get(key);
		    if (mapping) {
		        type = FieldType.format(field.getType().getName());
		        if(field.isAnnotationPresent(DateString.class))
		        	type = FieldType.Date;format=true;
		    } else {
		        FieldMapper fieldMapper = fieldMapperMap.get(key);
		        type = fieldMapper.type();
		        format = fieldMapper.format();
		    }
		    field.setAccessible(true);// 打破封装型
		    setInstanceAttrs(instance, value, type, format, field,"");
		}
	}
    
    
    private static void setInstanceAttrs(Object instance, Object value, FieldType type, boolean format, Field field,String columnPrimary)
			throws IllegalAccessException {
		if(value != null && !value.toString().equals("")){
			switch (type) {
				case Boolean:
					field.set(instance, Boolean.parseBoolean(String.valueOf(value)));// 设置属性值
					break;
				case Byte:
					field.set(instance, Byte.parseByte(String.valueOf(value)));// 设置属性值
					break;
				case Short:
					field.set(instance, Short.parseShort(String.valueOf(value)));// 设置属性值
					break;
				case Integer:
					field.set(instance, Integer.parseInt(String.valueOf(value)));// 设置属性值
					break;
				case Float:
					field.set(instance, Float.parseFloat(String.valueOf(value)));// 设置属性值
					break;
				case Long:
					field.set(instance, Long.parseLong(String.valueOf(value)));
					break;
				case Date:
					if(format){
						field.set(instance, DateUtil.date2Str(Timestamp.valueOf(String.valueOf(value))));// 设置属性值
					}else{
						if(String.valueOf(value).length() == 10){
							field.set(instance, DateUtil.str2Date(String.valueOf(value),"yyyy-MM-dd"));// 设置属性值
						}else{
							field.set(instance, Timestamp.valueOf(String.valueOf(value)));// 设置属性值
						}
					}
					break;
				case String:
					field.set(instance, String.valueOf(value));// 设置属性值
					break;
				case Double:
					field.set(instance, Double.parseDouble(String.valueOf(value)));// 设置属性值
					break;
				default:
					break;
			}
		}else if(value == null){
			if(type != null){
				if(type.toString().equals("String")){
					field.set(instance,"");// 设置属性值
				}
				if(type.toString().equals("Date") && format){
					field.set(instance,"");// 设置属性值
				}
			}
		}
	}
}
